#include <rtthread.h>
#include <board.h>
#include <rthw.h>
#include "rtdevice.h"
#include <fcntl.h>
#include <unistd.h>

#include <termios.h>

#ifdef RT_USING_SERIAL_X
#define RT_SERIAL_CONFIG_USER              \
{                                          \
    BAUD_RATE_115200, /* 115200 bits/s */  \
    DATA_BITS_8,      /* 8 databits */     \
    STOP_BITS_1,      /* 1 stopbit */      \
    PARITY_NONE,      /* No parity  */     \
    BIT_ORDER_LSB,    /* LSB first sent */ \
    NRZ_NORMAL,       /* Normal mode */    \
    RT_SERIAL_FIFO_BUFSZ, /* Buffer size */  \
    0                                      \
}
#elif defined(RT_USING_SERIAL_V2)
#define RT_SERIAL_CONFIG_USER              \
{                                          \
    BAUD_RATE_115200, /* 115200 bits/s */  \
    DATA_BITS_8,      /* 8 databits */     \
    STOP_BITS_1,      /* 1 stopbit */      \
    PARITY_NONE,      /* No parity  */     \
    BIT_ORDER_LSB,    /* LSB first sent */ \
    NRZ_NORMAL,       /* Normal mode */    \
    BSP_UART1_RX_BUFSIZE, /* rxBuf size */   \
    BSP_UART1_RX_BUFSIZE, /* txBuf size */   \
    0                                      \
}
#else
#define RT_SERIAL_CONFIG_USER              \
{                                          \
    BAUD_RATE_115200, /* 115200 bits/s */  \
    DATA_BITS_8,      /* 8 databits */     \
    STOP_BITS_1,      /* 1 stopbit */      \
    PARITY_NONE,      /* No parity  */     \
    BIT_ORDER_LSB,    /* LSB first sent */ \
    NRZ_NORMAL,       /* Normal mode */    \
    RT_SERIAL_RB_BUFSZ,                    \
    0                                      \
}
#endif

#define SERIAL_DEV_NAME   "/dev/uart1"

//#define SERIAL_CLOSEOPEN_TEST
//#define SERIAL_POLL_TEST
//#define SERIAL_FLUSH_TEST
//#define SERIAL_NONBLOCK_WRITE_TEST
//#define SERIAL_NONBLOCK_READ_TEST
//#define SERIAL_BLOCK_WRITE_TEST
//#define SERIAL_BLOCK_READ_TEST
//#define SERIAL_RW_TEST
#define SERIAL_SELECT_TEST

#if defined(SERIAL_SELECT_TEST)
#include <sys/time.h>
#include <sys/select.h>
#endif

static rt_thread_t uart_tid = RT_NULL;

#if defined(SERIAL_CLOSEOPEN_TEST)
static rt_bool_t close_open(int uart_dev)
{
    int i;

    write(uart_dev, "CLOSE & REOPEN\n", rt_strlen("close & reopen\n"));
    rt_thread_mdelay(1000);
    close(uart_dev);
    if ((uart_dev = open(SERIAL_DEV_NAME, O_RDWR)) < 0)
    {
        rt_kprintf("Open device: %s failed\n", SERIAL_DEV_NAME);
        return RT_FALSE;
    }
    write(uart_dev, "INT mode opened\n", rt_strlen("INT mode opened\n"));
    rt_thread_mdelay(1000);
    for (i = 0; i < 100000; i++) {
        close(uart_dev);
        if ((uart_dev = open(SERIAL_DEV_NAME, O_RDWR)) < 0)
        {
            rt_kprintf("Open device: %s failed\n", SERIAL_DEV_NAME);
            return RT_FALSE;
        }
    }
    rt_thread_mdelay(1000);
    close(uart_dev);
    if ((uart_dev = open(SERIAL_DEV_NAME, O_RDWR)) < 0)
    {
        rt_kprintf("Open device: %s failed\n", SERIAL_DEV_NAME);
        return RT_FALSE;
    }
    write(uart_dev, "REOPEN successfull\n", rt_strlen("REOPEN successfull\n"));
    
    return RT_TRUE;
}
#endif // SERIAL_CLOSEOPEN_TEST

#if defined(SERIAL_POLL_TEST)
static rt_bool_t pool_write(int uart_dev, rt_uint8_t *recvbuf)
{
    write(uart_dev, "\n\npoll WRITE\n", rt_strlen("\n\npoll WRITE\n"));
    rt_thread_mdelay(3000);
    write(uart_dev, recvbuf, 1024);
    write(uart_dev, recvbuf, 1024);
    write(uart_dev, recvbuf, 1024);
    write(uart_dev, recvbuf, 1024);
    write(uart_dev, recvbuf, 1024);
    write(uart_dev, "\npoll END\n", rt_strlen("\npoll END\n"));

    return RT_TRUE;
}
#endif // SERIAL_POLL_TEST

#if defined(SERIAL_FLUSH_TEST)
static rt_bool_t flush_write(int uart_dev, rt_uint8_t *recvbuf)
{
    int i;

    close(uart_dev);
    if ((uart_dev = open(SERIAL_DEV_NAME, O_RDWR)) < 0)
    {
        rt_kprintf("Open device: %s failed\n", SERIAL_DEV_NAME);
        return RT_FALSE;
    }
    write(uart_dev, "\n\nNO FLUSH, some data may be lost\n", rt_strlen("\n\nNO FLUSH, some data may be lost\n"));
    rt_thread_mdelay(1000);
    for (i = 0; i < 10; i++) {
    write(uart_dev, recvbuf, 1024);
    close(uart_dev);
    if ((uart_dev = open(SERIAL_DEV_NAME, O_RDWR)) < 0)
    {
        rt_kprintf("Open device: %s failed\n", SERIAL_DEV_NAME);
        return RT_FALSE;
    }
    }
    write(uart_dev, "\n\nFLUSH, no data lost\n", rt_strlen("\n\nflush, no data lost\n"));
    rt_thread_mdelay(1000);
    for (i = 0; i < 10; i++) {
    write(uart_dev, recvbuf, 1024);
#ifdef RT_USING_SERIAL_X
    fsync(uart_dev);
#endif
    close(uart_dev);
    if ((uart_dev = open(SERIAL_DEV_NAME, O_RDWR)) < 0)
    {
        rt_kprintf("Open device: %s failed\n", SERIAL_DEV_NAME);
        return RT_FALSE;
    }
    }
    return RT_TRUE;
}
#endif // SERIAL_FLUSH_TEST

#if defined(SERIAL_NONBLOCK_WRITE_TEST)
static rt_bool_t nonblock_write(int uart_dev, rt_uint8_t *recvbuf, rt_uint8_t *buf)
{
    rt_size_t wr_sz = 0, recv_sz = 0, tmp = 0, i;
    rt_tick_t tick1, tick2;
    for (tmp = 0; tmp < 1024; tmp++) {
        recvbuf[tmp] = '0' + (tmp % 60);
    }
    close(uart_dev);
    if ((uart_dev = open(SERIAL_DEV_NAME, O_RDWR | O_NONBLOCK)) < 0)
    {
        rt_kprintf("Open device: %s failed\n", SERIAL_DEV_NAME);
        return RT_FALSE;
    }
    write(uart_dev, "\n\nnonblock WRITE\n", rt_strlen("\n\nnonblock WRITE\n"));
    write(uart_dev, "3\n", 2);
    rt_thread_mdelay(1000);
    write(uart_dev, "2\n", 2);
    rt_thread_mdelay(1000);
    write(uart_dev, "1\n", 2);
    rt_thread_mdelay(1000);
    tick1 = rt_tick_get();
    tmp = 0;
    for (i = 0; i < 100; i++) {
        wr_sz = 0;
        while(wr_sz < 1024) {
            wr_sz += write(uart_dev, &recvbuf[wr_sz], 1024-wr_sz);
        }
        tmp += wr_sz;
    }
    tick2 = rt_tick_get();
    rt_sprintf(buf, "\nnonblock : write %d / 1024*10 bytes used %d ticks\n", tmp, tick2 - tick1);
    wr_sz = 0;
    tmp = rt_strlen(buf);
    while(wr_sz < tmp) {
        wr_sz += write(uart_dev, &buf[wr_sz], tmp-wr_sz);
    }

    rt_thread_mdelay(1000);
    tick1 = rt_tick_get();
    tmp = write(uart_dev, &recvbuf[wr_sz], 16);
    tick2 = rt_tick_get();
    rt_sprintf(buf, "\nnonblock : write %d / 16 bytes used %d ticks\n", tmp, tick2 - tick1);
    wr_sz = 0;
    tmp = rt_strlen(buf);
    while(wr_sz < tmp) {
        wr_sz += write(uart_dev, &buf[wr_sz], tmp-wr_sz);
    }
    rt_thread_mdelay(1000);
    tick1 = rt_tick_get();
    tmp = write(uart_dev, &recvbuf[wr_sz], 64);
    tick2 = rt_tick_get();
    rt_sprintf(buf, "\nnonblock : write %d / 64 bytes used %d ticks\n", tmp, tick2 - tick1);
    wr_sz = 0;
    tmp = rt_strlen(buf);
    while(wr_sz < tmp) {
        wr_sz += write(uart_dev, &buf[wr_sz], tmp-wr_sz);
    }
    rt_thread_mdelay(1000);
    tick1 = rt_tick_get();
    tmp = write(uart_dev, &recvbuf[wr_sz], 128);
    tick2 = rt_tick_get();
    rt_sprintf(buf, "\nnonblock : write %d / 128 bytes used %d ticks\n", tmp, tick2 - tick1);
    wr_sz = 0;
    tmp = rt_strlen(buf);
    while(wr_sz < tmp) {
        wr_sz += write(uart_dev, &buf[wr_sz], tmp-wr_sz);
    }

// nonblock ticks
    tick1 = rt_tick_get();
    tmp = 0;
    for (i = 0; i < 8; i++) {
        wr_sz = 0;
        while(wr_sz < 16) {
            wr_sz += write(uart_dev, &recvbuf[wr_sz], 16-wr_sz);
        }
        tmp += wr_sz;
    }
    tick2 = rt_tick_get();
    rt_sprintf(buf, "\n\nnonblock : write %d / 128 bytes used %d ticks\n", tmp, tick2 - tick1);
    wr_sz = 0;
    tmp = rt_strlen(buf);
    while(wr_sz < tmp) {
        wr_sz += write(uart_dev, &buf[wr_sz], tmp-wr_sz);
    }

    return RT_TRUE;
}
#endif // SERIAL_NONBLOCK_WRITE_TEST

#if defined(SERIAL_NONBLOCK_READ_TEST)
static rt_bool_t nonblock_read(int uart_dev, rt_uint8_t *recvbuf, rt_uint8_t *buf)
{
    rt_size_t recv_sz = 0;

    write(uart_dev, "\n\nnonblock READ\n", rt_strlen("\n\nnonblock READ\n"));
    write(uart_dev, "\nSEND somethings\n", rt_strlen("\nSEND somethings\n"));
    rt_thread_mdelay(1000);
    write(uart_dev, "3\n", 2);
    recv_sz = read(uart_dev, recvbuf, 512);
    rt_sprintf(buf, "\nnonblock : %d bytes read\n", recv_sz);
    write(uart_dev, buf, rt_strlen(buf));
    rt_thread_mdelay(1000);
    write(uart_dev, "2\n", 2);
    recv_sz = read(uart_dev, recvbuf, 512);
    rt_sprintf(buf, "\nnonblock : %d bytes read\n", recv_sz);
    write(uart_dev, buf, rt_strlen(buf));
    rt_thread_mdelay(1000);
    write(uart_dev, "1\n", 2);
    recv_sz = read(uart_dev, recvbuf, 512);
    rt_sprintf(buf, "\nnonblock : %d bytes read\n", recv_sz);
    write(uart_dev, buf, rt_strlen(buf));
    rt_thread_mdelay(1000);
    recv_sz = read(uart_dev, recvbuf, 512);
    rt_sprintf(buf, "\nnonblock : %d bytes read\n", recv_sz);
    write(uart_dev, buf, rt_strlen(buf));

    rt_sprintf(buf, "\rnonblock read END\n", recv_sz);
    write(uart_dev, buf, rt_strlen(buf));

#ifdef RT_USING_SERIAL_X
    fsync(uart_dev);
#endif
    return RT_TRUE;
}
#endif // SERIAL_NONBLOCK_READ_TEST

#if defined(SERIAL_BLOCK_WRITE_TEST)
static rt_bool_t block_write(int uart_dev, rt_uint8_t *recvbuf, rt_uint8_t *buf)
{
    rt_size_t wr_sz = 0, recv_sz = 0, tmp = 0, i;
    rt_tick_t tick1, tick2;
    for (tmp = 0; tmp < 1024; tmp++) {
        recvbuf[tmp] = '0' + (tmp % 60);
    }
    close(uart_dev);
    if ((uart_dev = open(SERIAL_DEV_NAME, O_RDWR)) < 0)
    {
        rt_kprintf("Open device: %s failed\n", SERIAL_DEV_NAME);
        return RT_FALSE;
    }
    write(uart_dev, "\n\nblock WRITE\n", rt_strlen("\n\nblock WRITE\n"));
    write(uart_dev, "3\n", 2);
    rt_thread_mdelay(1000);
    write(uart_dev, "2\n", 2);
    rt_thread_mdelay(1000);
    write(uart_dev, "1\n", 2);
    rt_thread_mdelay(1000);
    tick1 = rt_tick_get();
    wr_sz = 0;
    for (i = 0; i < 100; i++) {
        wr_sz += write(uart_dev, recvbuf, 1024);
    }
    tick2 = rt_tick_get();
    rt_sprintf(buf, "\nblock : write %d / 128 bytes use %d ticks\n", wr_sz, tick2 - tick1);
    write(uart_dev, buf, rt_strlen(buf));

    rt_thread_mdelay(1000);
    tick1 = rt_tick_get();
    wr_sz = write(uart_dev, recvbuf, 16);
    tick2 = rt_tick_get();
    rt_sprintf(buf, "\nblock : write %d / 16 bytes use %d ticks\n", wr_sz, tick2 - tick1);
    write(uart_dev, buf, rt_strlen(buf));
    rt_thread_mdelay(1000);
    tick1 = rt_tick_get();
    wr_sz = write(uart_dev, recvbuf, 64);
    tick2 = rt_tick_get();
    rt_sprintf(buf, "\nblock : write %d / 64 bytes use %d ticks\n", wr_sz, tick2 - tick1);
    write(uart_dev, buf, rt_strlen(buf));
    rt_thread_mdelay(1000);
    tick1 = rt_tick_get();
    wr_sz = write(uart_dev, recvbuf, 128);
    tick2 = rt_tick_get();
    rt_sprintf(buf, "\nblock : write %d / 128 bytes use %d ticks\n", wr_sz, tick2 - tick1);
    write(uart_dev, buf, rt_strlen(buf));
// block ticks
    tick1 = rt_tick_get();
    wr_sz = 0;
    for (i = 0; i < 8; i++) {
        wr_sz += write(uart_dev, recvbuf, 16);
    }
    tick2 = rt_tick_get();
    rt_sprintf(buf, "\n\nblock : write %d / 128 bytes use %d ticks\n", wr_sz, tick2 - tick1);
    write(uart_dev, buf, rt_strlen(buf));

    return RT_TRUE;
}
#endif // SERIAL_BLOCK_WRITE_TEST

#if defined(SERIAL_BLOCK_READ_TEST)
static rt_bool_t block_read(int uart_dev, rt_uint8_t *recvbuf, rt_uint8_t *buf)
{
    rt_size_t recv_sz = 0;

    write(uart_dev, "\n\nblock READ\n", rt_strlen("\n\nblock READ\n"));
    write(uart_dev, "\nSEND somethings\n", rt_strlen("\nSEND somethings\n"));
    rt_thread_mdelay(1000);
    write(uart_dev, "3\n", 2);
    recv_sz = read(uart_dev, recvbuf, 512);
    rt_sprintf(buf, "\nblock : %d bytes read\n", recv_sz);
    write(uart_dev, buf, rt_strlen(buf));
    rt_thread_mdelay(1000);
    write(uart_dev, "2\n", 2);
    recv_sz = read(uart_dev, recvbuf, 512);
    rt_sprintf(buf, "\nblock : %d bytes read\n", recv_sz);
    write(uart_dev, buf, rt_strlen(buf));
    rt_thread_mdelay(1000);
    write(uart_dev, "1\n", 2);
    recv_sz = read(uart_dev, recvbuf, 512);
    rt_sprintf(buf, "\nblock : %d bytes read\n", recv_sz);
    write(uart_dev, buf, rt_strlen(buf));
    rt_thread_mdelay(1000);
    recv_sz = read(uart_dev, recvbuf, 512);
    rt_sprintf(buf, "\rblock : %d bytes read\n", recv_sz);
    write(uart_dev, buf, rt_strlen(buf));

    rt_sprintf(buf, "\rblock read END\n", recv_sz);
    write(uart_dev, buf, rt_strlen(buf));
#ifdef RT_USING_SERIAL_X
    fsync(uart_dev);
#endif
    return RT_TRUE;
}
#endif // SERIAL_BLOCK_READ_TEST

static int termio_config(int uart_dev, int baud, char parity, int data_bit,
                         int stop_bit)
{
    struct termios tios;
    speed_t speed;
    
    memset(&tios, 0, sizeof(struct termios));
    
    /* C_ISPEED     Input baud (new interface)
       C_OSPEED     Output baud (new interface)
    */
    switch (baud) {
    case 110:
        speed = B110;
        break;
    case 300:
        speed = B300;
        break;
    case 600:
        speed = B600;
        break;
    case 1200:
        speed = B1200;
        break;
    case 2400:
        speed = B2400;
        break;
    case 4800:
        speed = B4800;
        break;
    case 9600:
        speed = B9600;
        break;
    case 19200:
        speed = B19200;
        break;
    case 38400:
        speed = B38400;
        break;
#ifdef B57600
    case 57600:
        speed = B57600;
        break;
#endif
#ifdef B115200
    case 115200:
        speed = B115200;
        break;
#endif
#ifdef B230400
    case 230400:
        speed = B230400;
        break;
#endif
#ifdef B460800
    case 460800:
        speed = B460800;
        break;
#endif
#ifdef B500000
    case 500000:
        speed = B500000;
        break;
#endif
#ifdef B576000
    case 576000:
        speed = B576000;
        break;
#endif
#ifdef B921600
    case 921600:
        speed = B921600;
        break;
#endif
#ifdef B1000000
    case 1000000:
        speed = B1000000;
        break;
#endif
#ifdef B1152000
   case 1152000:
        speed = B1152000;
        break;
#endif
#ifdef B1500000
    case 1500000:
        speed = B1500000;
        break;
#endif
#ifdef B2500000
    case 2500000:
        speed = B2500000;
        break;
#endif
#ifdef B3000000
    case 3000000:
        speed = B3000000;
        break;
#endif
#ifdef B3500000
    case 3500000:
        speed = B3500000;
        break;
#endif
#ifdef B4000000
    case 4000000:
        speed = B4000000;
        break;
#endif
    default:
        speed = B9600;
        break;
    }

    /* Set the baud rate */
    if ((cfsetispeed(&tios, speed) < 0) ||
        (cfsetospeed(&tios, speed) < 0)) {
        return -1;
    }

    /* C_CFLAG      Control options
       CLOCAL       Local line - do not change "owner" of port
       CREAD        Enable receiver
    */
    tios.c_cflag |= (CREAD | CLOCAL);
    /* CSIZE, HUPCL, CRTSCTS (hardware flow control) */

    /* Set data bits (5, 6, 7, 8 bits)
       CSIZE        Bit mask for data bits
    */
    tios.c_cflag &= ~CSIZE;
    switch (data_bit) {
    case 5:
        tios.c_cflag |= CS5;
        break;
    case 6:
        tios.c_cflag |= CS6;
        break;
    case 7:
        tios.c_cflag |= CS7;
        break;
    case 8:
    default:
        tios.c_cflag |= CS8;
        break;
    }

    /* Stop bit (1 or 2) */
    if (stop_bit == 1)
        tios.c_cflag &=~ CSTOPB;
    else /* 2 */
        tios.c_cflag |= CSTOPB;

    /* PARENB       Enable parity bit
       PARODD       Use odd parity instead of even */
    if (parity == 'N') {
        /* None */
        tios.c_cflag &=~ PARENB;
    } else if (parity == 'E') {
        /* Even */
        tios.c_cflag |= PARENB;
        tios.c_cflag &=~ PARODD;
    } else {
        /* Odd */
        tios.c_cflag |= PARENB;
        tios.c_cflag |= PARODD;
    }

    /* Raw input */
    tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

    if (parity == 'N') {
        /* None */
        tios.c_iflag &= ~INPCK;
    } else {
        tios.c_iflag |= INPCK;
    }

    /* Software flow control is disabled */
    tios.c_iflag &= ~(IXON | IXOFF | IXANY);

    /* Raw ouput */
    tios.c_oflag &=~ OPOST;

    /* Unused because we use open with the NDELAY option */
    tios.c_cc[VMIN] = 0;
    tios.c_cc[VTIME] = 0;

    if (tcsetattr(uart_dev, TCSANOW, &tios) < 0) {
        return -1;
    }
    
    return 0;
}

static void uart_test_thread(void *parameter)
{
    int uart_dev;
    rt_uint8_t *recvbuf = RT_NULL, *buf = RT_NULL;
    rt_size_t wr_sz = 0, recv_sz = 0, tmp = 0, i;
    rt_tick_t tick1, tick2;


    if ((uart_dev = open(SERIAL_DEV_NAME, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL)) < 0)
    {
        rt_kprintf("Open device: %s failed\n", SERIAL_DEV_NAME);
        return;
    }

    termio_config(uart_dev, 115200, 'N', 8, 1);
    
    write(uart_dev, "POLL mode opened\n", rt_strlen("POLL mode opened\n"));
#ifdef RT_USING_SERIAL_X
    fsync(uart_dev);
#endif
    recvbuf = rt_malloc(1024);
    buf = rt_malloc(64);
//    rt_memset(recvbuf, 0x5A, 512);
    for (tmp = 0; tmp < 1024; tmp++) {
        recvbuf[tmp] = '0' + (tmp % 60);
    }

// close reopen test
#if defined(SERIAL_CLOSEOPEN_TEST)
    close_open(uart_dev);
    rt_thread_mdelay(1000);
#endif // SERIAL_CLOSEOPEN_TEST

#if defined(SERIAL_POLL_TEST)
    pool_write(uart_dev, recvbuf);
    rt_thread_mdelay(1000);
#endif // SERIAL_POLL_TEST

// flush test
#if defined(SERIAL_FLUSH_TEST)
    flush_write(uart_dev, recvbuf);
#endif // SERIAL_FLUSH_TEST

// nonblock write ,more than tx buffer room
#if defined(SERIAL_NONBLOCK_WRITE_TEST)
    nonblock_write(uart_dev, recvbuf, buf);
    rt_thread_mdelay(1000);
#endif // SERIAL_NONBLOCK_WRITE_TEST

// nonblock read
#if defined(SERIAL_NONBLOCK_READ_TEST)
    nonblock_read(uart_dev, recvbuf, buf);
#endif // SERIAL_NONBLOCK_READ_TEST

// block write ,more than tx buffer room
#if defined(SERIAL_BLOCK_WRITE_TEST)
    block_write(uart_dev, recvbuf, buf);
    rt_thread_mdelay(1000);
#endif // SERIAL_BLOCK_WRITE_TEST

// block read
#if defined(SERIAL_BLOCK_READ_TEST)
    block_read(uart_dev, recvbuf, buf);
#endif // SERIAL_BLOCK_READ_TEST

// read write loopback test
    close(uart_dev);
    if ((uart_dev = open(SERIAL_DEV_NAME, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL)) < 0)
    {
        rt_kprintf("Open device: %s failed\n", SERIAL_DEV_NAME);
        return;
    }

    termio_config(uart_dev, 115200, 'N', 8, 1);

    write(uart_dev, "\n\nblock LOOPBACK\n", rt_strlen("\n\nblock loopback\n"));

#if defined(SERIAL_SELECT_TEST)
    int rc;
    fd_set rset;
    struct timeval tv;

    tv.tv_sec = 3;
    tv.tv_usec = 0;
    write(uart_dev, "Using select\n", rt_strlen("Using select\n"));
#endif

    while (1) {
#if defined(SERIAL_WRITE_TEST)
        write(uart_dev, recvbuf, 12);
        rt_thread_mdelay(100);
#elif defined(SERIAL_READ_TEST)
        recv_sz = read(uart_dev, recvbuf, 128);
        rt_thread_delay(2);
#elif defined(SERIAL_RW_TEST)
        recv_sz = read(uart_dev, recvbuf, 128);
        if (recv_sz > 0) {
            recvbuf[recv_sz] = 0;
            write(uart_dev, recvbuf, recv_sz);
        }
        rt_thread_delay(2);
#elif defined(SERIAL_SELECT_TEST)

        FD_ZERO(&rset);
        FD_SET(uart_dev, &rset);

        rc = select(uart_dev+1, &rset, NULL, NULL, &tv);
        if (rc <= 0) {
            continue;
        }
        if (FD_ISSET(uart_dev, &rset)) {
            recv_sz = read(uart_dev, recvbuf, 128);
            if (recv_sz > 0) {
                recvbuf[recv_sz] = 0;
                wr_sz = write(uart_dev, recvbuf, recv_sz);
                rt_kprintf("(%d %d)", recv_sz, wr_sz);
            }
            rt_thread_delay(2);
        }
#endif
    }
}

int uart_posix_init(void)
{
    uart_tid = rt_thread_create("uartX",              
                           uart_test_thread, RT_NULL,
                           2048,
                           0,
                           20);
    if (uart_tid != RT_NULL)
        rt_thread_startup(uart_tid);

    return 0;
}
INIT_APP_EXPORT(uart_posix_init);
